<?php
namespace apple;

use jwt\JWT;
use jwt\Key;
use jwt\SignatureInvalidException;

class NotifyIap
{
    // 去苹果官方下载根证书（第4个） https://www.apple.com/certificateauthority/
    //命令如下: openssl x509 -inform der -in AppleRootCA-G3.cer -out AppleRootCA-G3.pem
    private function validateAppleRootCA($header)
    {
        $lastIndex = count($header['x5c']) - 1;
        $certificate = $this->getCertificate($header, $lastIndex);
        $Path ="../key/AppleRootCA-G3.pem";
        $appleRootCA = file_get_contents($Path);
        return $certificate == $appleRootCA;
    }
 
    private function getCertificate($headerJson, $certificateIndex)
    {
        $certificate = '-----BEGIN CERTIFICATE-----' . PHP_EOL;
        $certificate .= chunk_split($headerJson['x5c'][$certificateIndex], 64, PHP_EOL);
        $certificate .= '-----END CERTIFICATE-----' . PHP_EOL;
 
        return $certificate;
    }
 
    private function decodeCertificate($jwt, $headerJson, $certificateIndex = 0)
    {
        $certificate = $this->getCertificate($headerJson, 0);
 
        $cert_object = openssl_x509_read($certificate);
        $pkey_object = openssl_pkey_get_public($cert_object);
        $pkey_array = openssl_pkey_get_details($pkey_object);
        $publicKey = $pkey_array['key'];

        try {
            $jwsDecoded = JWT::decode($jwt, new Key($publicKey, 'ES256'));
            var_dump($jwsDecoded);die();
            $jwsParsed = (array)$jwsDecoded;
            return $jwsParsed;
        } catch (SignatureInvalidException $e) {
            throw new \Exception('signature invalid');
        }
    }

    public function decode($signedPayload){
       /*通知类型
             https://developer.apple.com/documentation/appstoreservernotifications/notificationtype
             CONSUMPTION_REQUEST 表示客户针对消耗品内购发起退款申请
             DID_CHANGE_RENEWAL_PREF 对其订阅计划进行了更改 如果subtype是UPGRADE，则用户升级了他们的订阅;如果subtype是DOWNGRADE，则用户将其订阅降级或交叉分级
             DID_CHANGE_RENEWAL_STATUS 通知类型及其subtype指示用户对订阅续订状态进行了更改
             DID_FAIL_TO_RENEW 一种通知类型及其subtype指示订阅由于计费问题而未能续订
             DID_RENEW 一种通知类型，连同其subtype指示订阅成功续订
             EXPIRED 一种通知类型及其subtype指示订阅已过期
             GRACE_PERIOD_EXPIRED 表示计费宽限期已结束，无需续订，因此您可以关闭对服务或内容的访问
             OFFER_REDEEMED 一种通知类型，连同其subtype指示用户兑换了促销优惠或优惠代码。 subtype DID_RENEW
             PRICE_INCREASE 一种通知类型，连同其subtype指示系统已通知用户订阅价格上涨
             REFUND 表示 App Store 成功为消耗性应用内购买、非消耗性应用内购买、自动续订订阅或非续订订阅的交易退款
             REFUND_DECLINED 表示 App Store 拒绝了应用开发者发起的退款请求
             RENEWAL_EXTENDED 表示 App Store 延长了开发者要求的订阅续订日期
             REVOKE表示 用户有权通过家庭共享获得的应用内购买不再通过共享获得
             SUBSCRIBED 一种通知类型，连同其subtype指示用户订阅了产品
             1. 用户主动取消订阅notificationType:DID_CHANGE_RENEWAL_STATUS
             2. 用户取消订阅，又重新开通连续订阅notificationType: SUBSCRIBED  subtype: RESUBSCRIBE
             3. 用户首次开通订阅notificationType: SUBSCRIBED  subtype: INITIAL_BUY
             */
        $data = $this->verifyToken($signedPayload);
       
        $data['payload']['data']['signedTransactionInfo'] = $this->verifyToken($data['payload']['data']['signedTransactionInfo']);
        $data['payload']['data']['signedRenewalInfo'] = $this->verifyToken($data['payload']['data']['signedRenewalInfo']);
        
       
        // if($this->validateAppleRootCA($data['header'])){
        //     $data_decode = $this->decodeCertificate($signedPayload, $data['header'], 0);
        // }
        return  $data;
    }

 

    /**
     * 验证token是否有效,默认验证exp,nbf,iat时间
     * @param string $Token 需要验证的token
     * @return bool|string
     */
    public function verifyToken($token)
    {
        //header：主要声明了 JWT 的签名算法；
        //payload：主要承载了各种声明并传递明文数据；
        //signture：拥有该部分的 JWT 被称为 JWS，也就是签了名的 JWS。
        list($header, $payload, $signture) = explode('.', $token);
        if (empty($header) || empty($payload) || empty($signture)) {
            return [];
        }
     
        $header =  json_decode($this->base64UrlDecode($header), JSON_OBJECT_AS_ARRAY);
         //获取jwt算法
        if ($header['alg'] != 'ES256') {
            return [];
        }
        $payload = json_decode($this->base64UrlDecode($payload), JSON_OBJECT_AS_ARRAY);

        $data = [
            'header' => $header,
            'payload' => $payload,
            'signture' => $signture,
        ];
        return $data;
    }


    /**
     * base64UrlEncode   https://jwt.io/  中base64UrlEncode编码实现
     * @param string $input 需要编码的字符串
     * @return string
     */
    private  function base64UrlEncode($input)
    {
        return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
    }

    /**
     * base64UrlEncode  https://jwt.io/  中base64UrlEncode解码实现
     * @param string $input 需要解码的字符串
     * @return bool|string
     */
    private  function base64UrlDecode($input)
    {
        $remainder = strlen($input) % 4;
        if ($remainder) {
            $addlen = 4 - $remainder;
            $input .= str_repeat('=', $addlen);
        }
        return base64_decode(strtr($input, '-_', '+/'));
    }
}
